package com.wdk.processor;

import com.google.auto.service.AutoService;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.Filer;
import javax.annotation.processing.Messager;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
import javax.lang.model.util.Elements;
import javax.lang.model.util.Types;


@AutoService(Processor.class)
public class MyProcessor extends AbstractProcessor {

    /**
     * Types是一个用来处理TypeMirror的工具
     */
    private Types typesUtils;
    /**
     * Elements是一个用来处理Element的工具
     */
    private Elements elements;
    /**
     * 生成java源码
     */
    private Filer filer;
    /**
     * Messager提供给注解处理器一个报告错误、警告以及提示信息的途径。
     * 它不是注解处理器开发者的日志工具，
     * 而是用来写一些信息给使用此注解器的第三方开发者的
     */
    private Messager messager;

    private Locale locale;
    private SourceVersion sourceVersion;
    private Map<String, String> optMap;


    //===============核心设置==================
    private Map<String, MtopAnnotationClass> mAnnotatedClassMap;


    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);

        //===============核心设置==================
        typesUtils = processingEnv.getTypeUtils();
        filer = processingEnv.getFiler();

        //ProcessingEnvironment可以获取的对象
        elements = processingEnv.getElementUtils();
        messager = processingEnv.getMessager();
        locale = processingEnv.getLocale();
        sourceVersion = processingEnv.getSourceVersion();
        optMap = processingEnv.getOptions();
        //
        mAnnotatedClassMap = new TreeMap<>();
    }

    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnv) {
        mAnnotatedClassMap.clear();

        //创建自定义注解处理类
        try {
            processMyView(roundEnv);
        } catch (Exception e) {
            System.out.println("异常:" + e.toString());
        }

        //将自定义注解处理类，写入文件
        for (MtopAnnotationClass annotationClass : mAnnotatedClassMap.values()) {
            try {
                annotationClass.generateFiler().writeTo(filer);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return true;
    }

    /**
     * 创建处理类,处理自定义注解
     *
     * @param roundEnv
     */
    private void processMyView(RoundEnvironment roundEnv) {
        for (Element element : roundEnv.getElementsAnnotatedWith(RequestFit.class)) {
            MtopAnnotationClass annotationClass = createMyAnnotationClass(element);
            MtopSendField bindViewField = new MtopSendField(element);
            annotationClass.addField(bindViewField);

            System.out.println("processMyView annotatedClass: " + annotationClass);
            System.out.println("processMyView MtopSendField: " + bindViewField);
        }

    }

    /**
     * 获取每一个Element的处理类,并将生成的处理类保存到map中
     *
     * @param element
     * @return
     */
    private MtopAnnotationClass createMyAnnotationClass(Element element) {
        TypeElement typeElement = (TypeElement) element.getEnclosingElement();
        String fullName = typeElement.getQualifiedName().toString();
        System.out.println("getAnnotatedClass typeElement: " + typeElement);
        MtopAnnotationClass annotationClass = mAnnotatedClassMap.get(fullName);
        //如果集合中不存在，则添加到集合中
        if (annotationClass == null) {
            //创建注解处理类
            annotationClass = new MtopAnnotationClass(typeElement, elements);
            mAnnotatedClassMap.put(fullName, annotationClass);
        }
        return annotationClass;
    }


    /**
     * (3)必须重写的方法，
     * <p>
     * 处理器想要处理的自定义注解
     *
     * @return
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> types = new LinkedHashSet<>();
        for (Class<? extends Annotation> annotation : getSupportedAnnotations()) {
            types.add(annotation.getCanonicalName());
        }
        return types;
    }

    /**
     * <p>
     * 将自定义的注解添加到set列表中
     * <p>
     * 模仿butterKnife的写法,给（3）getSupportedAnnotationTypes使用
     *
     * @return
     */
    private Set<Class<? extends Annotation>> getSupportedAnnotations() {
        Set<Class<? extends Annotation>> annotations = new LinkedHashSet<>();
        annotations.add(RequestFit.class);
//        annotations.add(MyBindAct.class);
        return annotations;
    }


    /**
     * (4)必须重写的方法:
     * <p>
     * 指定使用的Java版本，通常这里返回SourceVersion.latestSupported()，默认返回SourceVersion.RELEASE_6
     *
     * @return 使用的Java版本
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }


}